#ifndef IO_FILE_BASE_H_
#define IO_FILE_BASE_H_

#include <fermat/dio/request.h>

#include <cassert>
#include <ostream>
#include <string>

namespace fermat {

class FileBase : public std::enable_shared_from_this<FileBase> {
public:
    static const bool debug = false;

    typedef  size_t offset_type;
    typedef  size_t size_type;

    /**********************************************************************
    * Definition of acceptable file open modes.  Various open modes in a file
    * system must be converted to this set of acceptable modes.
    ***********************************************************************/
    enum open_mode {
        //! only reading of the file is allowed
        RDONLY = 1,
        //! only writing of the file is allowed
        WRONLY = 2,
        //! read and write of the file are allowed
        RDWR = 4,
        //! in case file does not exist no error occurs and file is newly
        //! created
        CREAT = 8,
        //! I/Os proceed bypassing file system buffers, i.e. unbuffered I/O.
        //! Tries to open with appropriate flags, if fails print warning and
        //! open normally.
        DIRECT = 16,
        //! once file is opened its length becomes zero
        TRUNC = 32,
        //! open the file with O_SYNC | O_DSYNC | O_RSYNC flags set
        SYNC = 64,
        //! do not acquire an exclusive lock by default
        NO_LOCK = 128,
        //! implies DIRECT, fail if opening with DIRECT flag does not work.
        REQUIRE_DIRECT = 256
    };

    static const int DEFAULT_QUEUE = -1;
    static const int DEFAULT_LINUXAIO_QUEUE = -2;
    static const int NO_ALLOCATOR = -1;
    static const unsigned int DEFAULT_DEVICE_ID = (unsigned int)(-1);
public:

    virtual RequestPtr aread(
        void* buffer, offset_type offset, size_type bytes,
        const CompletionHandler& on_cmpl = CompletionHandler()) = 0;

    virtual RequestPtr awrite(
        void* buffer, offset_type offset, size_type bytes,
        const CompletionHandler& on_cmpl = CompletionHandler()) = 0;

    virtual int serve(void* buffer, offset_type offset, size_type bytes,
                       Request::ReadOrWriteType type) = 0;
    virtual void set_size(offset_type newsize) = 0;

    virtual offset_type size() = 0;

    virtual int get_queue_id() const = 0;

    virtual int get_allocator_id() const = 0;

    virtual void lock() = 0;

    virtual ~FileBase() { }

    virtual const char * io_type() const = 0;
	virtual int unlink() = 0;

	virtual void close() = 0;

	virtual int truncate(size_t length) = 0;

    virtual void discard(offset_type offset, offset_type len) {
        (void)offset;
        (void)len;
    }
	virtual void close_remove() { }
	
public:
	bool need_alignment() const { return _need_alignment; }
	int  error() { return _saved_errno; }
	void setError(int err) { _saved_errno = err; }
	unsigned int get_device_id() const {
		return _device_id;
	}
protected:
	 explicit FileBase(unsigned int device_id = DEFAULT_DEVICE_ID)
        : _device_id(device_id), _saved_errno(0){ }


protected:
    bool         _need_alignment;

    unsigned int _device_id;
	int          _saved_errno; 
	
private:
	
    FileBase(const FileBase&) ;
    FileBase& operator = (const FileBase&) ;
 
};

typedef std::shared_ptr<FileBase> FileBasePtr;


} 

#endif 
